' The Cue/Prompt Feature was adapted from Daniel Moth's example at http://www.danielmoth.com/Blog/2006/07/textbox-with-cue-banner-support-for.html

Imports System
Imports System.Windows.Forms
Imports System.Diagnostics
Imports System.Drawing
Imports System.ComponentModel
Imports System.ComponentModel.Design

<Designer(GetType(TextboxCueSmartTagDesigner))> _
Partial Public Class TextboxCue
  Inherits TextBox

  Private Const DEFAULTPROMPT As String = "Enter a text prompt"

  Private _textPrompt As String = DEFAULTPROMPT
  Private _usePrompt As Boolean

#Region "Overridden Events"

  Protected Overrides Sub OnGotFocus(ByVal e As EventArgs)
    MyBase.OnGotFocus(e)
    If (Me.UsePrompt) Then
      Me.UsePrompt = False
      Me.Text = String.Empty

    End If

  End Sub

  Protected Overrides Sub OnLostFocus(ByVal e As EventArgs)
    If (Me.TextLength = 0 OrElse Me.Text = Me.TextPrompt) Then
      Me.UsePrompt = True
      Me.Text = Me.TextPrompt
    End If

    MyBase.OnLostFocus(e)

  End Sub

  Protected Overrides Sub OnParentChanged(ByVal e As System.EventArgs)
    If String.IsNullOrEmpty(Me.Text) Then
      Me.UsePrompt = True
      Me.Text = Me.TextPrompt
    End If
    MyBase.OnParentChanged(e)
  End Sub

#End Region

#Region "Overridded Properties"

  Public Overrides Property Text() As String
    Get
      If Me.UsePrompt Then
        Return String.Empty
      End If
      Return MyBase.Text
    End Get
    Set(ByVal value As String)
      If Me.UsePrompt AndAlso (Not String.IsNullOrEmpty(value) AndAlso value <> Me.TextPrompt) Then
        Me.UsePrompt = False
      End If
      If String.IsNullOrEmpty(value) AndAlso Not Me.Focused AndAlso Not String.IsNullOrEmpty(Me.TextPrompt) Then
        Me.UsePrompt = True
        MyBase.Text = Me.TextPrompt
        Return
      End If

      MyBase.Text = value
    End Set
  End Property

#End Region

#Region "Public Properties"
  <System.ComponentModel.Category("Data"), DefaultValue(DEFAULTPROMPT)> _
  Public Property TextPrompt() As String
    Get
      Return Me._textPrompt

    End Get
    Set(ByVal value As String)
      Me._textPrompt = value
      If Me.UsePrompt AndAlso Not String.IsNullOrEmpty(Me._textPrompt) Then
        Me.Text = value
      End If
    End Set

  End Property

#End Region

#Region "Private Properties"
  Private Property UsePrompt() As Boolean
    Get
      Return Me._usePrompt

    End Get

    Set(ByVal value As Boolean)

      Me._usePrompt = value

      If _usePrompt Then
        Me.Font = New Font(Me.Font.Name, Me.Font.Size, FontStyle.Italic)
        Me.ForeColor = Color.Gray

      Else
        '// TODO don't hardcode the user given values.
        Me.Font = New Font(Me.Font.Name, Me.Font.Size, FontStyle.Regular)
        Me.ForeColor = Color.Black

      End If

    End Set
  End Property

#End Region

#Region "Generated Code"
  'Control overrides dispose to clean up the component list.
  <System.Diagnostics.DebuggerNonUserCode()> _
  Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If disposing AndAlso components IsNot Nothing Then
      components.Dispose()
    End If
    MyBase.Dispose(disposing)
  End Sub

  'Required by the Control Designer
  Private components As System.ComponentModel.IContainer

  ' NOTE: The following procedure is required by the Component Designer
  ' It can be modified using the Component Designer.  Do not modify it
  ' using the code editor.
  <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
  <System.Diagnostics.DebuggerStepThrough()> _
  Private Sub InitializeComponent()
    components = New System.ComponentModel.Container()
  End Sub

#End Region

End Class

#Region "Smart Tag Support"

'///////////////////////////////////////////////////////////////
'Designer for the ColorLabel control with support for a smart 
' tag panel.
'///////////////////////////////////////////////////////////////
'Must add reference to System.Design.dll
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
Public Class TextboxCueSmartTagDesigner
  Inherits System.Windows.Forms.Design.ControlDesigner

  Private lists As DesignerActionListCollection

  'Use pull model to populate smart tag menu.
  Public Overrides ReadOnly Property ActionLists() _
  As DesignerActionListCollection
    Get
      If lists Is Nothing Then
        lists = New DesignerActionListCollection()
        lists.Add( _
        New TextboxCueSmartTagActionList(Me.Component))
      End If
      Return lists
    End Get
  End Property
End Class

'///////////////////////////////////////////////////////////////
'DesignerActionList-derived class defines smart tag entries and
' resultant actions.
'///////////////////////////////////////////////////////////////
Public Class TextboxCueSmartTagActionList
  Inherits System.ComponentModel.Design.DesignerActionList

  Private _TextboxCue As TextboxCue

  <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")> _
  Private designerActionUISvc As DesignerActionUIService

  'The constructor associates the control 
  'with the smart tag list.
  Public Sub New(ByVal component As IComponent)

    MyBase.New(component)
    Me._TextboxCue = component

    ' Cache a reference to DesignerActionUIService, so the
    ' DesigneractionList can be refreshed.
    Me.designerActionUISvc = CType(GetService(GetType(DesignerActionUIService)), DesignerActionUIService)

  End Sub

  'Helper method to retrieve control properties. Use of 
  ' GetProperties enables undo and menu updates to work properly.
  Private Function GetPropertyByName(ByVal propName As String) _
  As PropertyDescriptor
    Dim prop As PropertyDescriptor
    prop = TypeDescriptor.GetProperties(_TextboxCue)(propName)
    If prop Is Nothing Then
      Throw New ArgumentException( _
      "Matching property not found!", propName)
    Else
      Return prop
    End If
  End Function


  Public Property TextPrompt() As String
    Get
      Return _TextboxCue.TextPrompt
    End Get
    Set(ByVal value As String)
      GetPropertyByName("TextPrompt").SetValue(_TextboxCue, value)
    End Set
  End Property

  'Implementation of this virtual method creates smart tag  
  ' items, associates their targets, and collects into list.
  Public Overrides Function GetSortedActionItems() _
  As DesignerActionItemCollection
    Dim items As New DesignerActionItemCollection()

    items.Add( _
    New DesignerActionPropertyItem( _
    "TextPrompt", _
    "Text Prompt", _
    "", _
    "Sets the Prompt or Cue text to display when the control is empty."))

    Return items
  End Function

End Class

#End Region

#Region "Original TextBoxCue code from Daniel Moth"

'using System;
'using System.Windows.Forms;
'using System.Diagnostics;
'using System.Drawing;
'using System.ComponentModel;

'public partial class TextBoxWithPrompt : TextBox
'{
'  // originated at http://danielmoth.com/Blog
'  protected override void OnGotFocus(EventArgs e)
'  {
'    base.OnGotFocus(e);
'    if (this.UsePrompt)
'    {
'      this.UsePrompt = false;
'      this.Text = string.Empty;
'    }
'  }

'  protected override void OnLostFocus(EventArgs e)
'  {
'    if (this.TextLength == 0 || this.Text == this.TextPrompt)
'    {
'      this.UsePrompt = true;
'      this.Text = this.TextPrompt;
'    }
'    base.OnLostFocus(e);
'  }

'  private string textPrompt = "enter a moth";
'  public string TextPrompt
'  {
'    get { return textPrompt; }
'    set
'    {
'      textPrompt = value;
'      if (this.UsePrompt && !string.IsNullOrEmpty(this.textPrompt))
'      {
'        this.Text = value;
'      }
'    }
'  }

'  private bool usePrompt;
'  private bool UsePrompt
'  {
'    get { return usePrompt; }
'    set
'    {
'      usePrompt = value;
'      if (usePrompt)
'      {
'        this.Font = new Font(this.Font.Name, this.Font.Size, FontStyle.Italic);
'        this.ForeColor = Color.Gray;
'      }
'      else
'      {
'        // TODO don't hardcode the user given values.
'        this.Font = new Font(this.Font.Name, this.Font.Size, FontStyle.Regular);
'        this.ForeColor = Color.Black;
'      }
'    }
'  }

'  protected override void OnParentChanged(EventArgs e)
'  {
'    if (string.IsNullOrEmpty(this.Text))
'    {
'      this.UsePrompt = true;
'      this.Text = this.TextPrompt;
'    }
'    base.OnParentChanged(e);
'  }

'  public override string Text
'  {
'    get
'    {
'      if (this.UsePrompt)
'      {
'        return string.Empty;
'      }
'      return base.Text;
'    }
'    set
'    {
'      if (this.UsePrompt && (!string.IsNullOrEmpty(value) && value != this.TextPrompt))
'      {
'        this.UsePrompt = false;
'      }

'      if (string.IsNullOrEmpty(value) && !this.Focused && !string.IsNullOrEmpty(this.textPrompt))
'      {
'        this.UsePrompt = true;
'        this.Text = this.TextPrompt;
'        return;
'      }

'      base.Text = value;
'    }
'  }
'}
#End Region

